import scala.annotation.tailrec

object TestFunction {
  def main(args: Array[String]): Unit = {
    // （1）函数定义
    def f(arg: String): Unit = {
      println(arg)
    }

    // （2）函数调用
    // 函数名（参数）
    f("hello world")

    // (2)方法可以进行重载和重写，程序可以执行
    def main(): Unit = {

    }


    //    def main(args: Array[String]): Unit = {
    //      // （1）Scala语言可以在任何的语法结构中声明任何的语法
    //      import java.util.Date
    //      new Date()
    //
    //      // (2)函数没有重载和重写的概念，程序报错
    //      def test(): Unit = {
    //        println("无参，无返回值")
    //      }
    //
    //      test()
    //
    //      def test(name: String): Unit = {
    //        println()
    //      }
    //
    //      //（3）Scala中函数可以嵌套定义
    //      def test2(): Unit = {
    //
    //        def test3(name: String): Unit = {
    //          println("函数可以嵌套定义")
    //        }
    //      }
    //    }

    // 阶乘
    // 递归算法
    // 1) 方法调用自身
    // 2) 方法必须要有跳出的逻辑
    // 3) 方法调用自身时，传递的参数应该有规律
    // 4) scala中的递归必须声明函数返回值类型

    println(test(5))

    /**
     * @ 5.2.6 控制抽象
     * 1）值调用：把计算后的值传递过去
     * */
    def function = () => {
      println("f...")
      10
    }

    foo(function())

    /**
     * 2）名调用：把代码传递过去
     * */

    fooo(function())

    // 注意：Java只有值调用；Scala既有值调用，又有名调用。

    var i: Int = 1
    myWhile(i <= 10) {
      println(i)
      i += 1
    }

    /**
     * @ 5.2.7 惰性加载
     * 1）说明
     * 当函数返回值被声明为lazy时，函数的执行将被推迟，直到我们首次对此取值，该函
     * 数才会执行。这种函数我们称之为惰性函数。
     * 注意：lazy不能修饰var类型的变量
     * */
    lazy val res = sum(10, 30)
    println("----------------")
    println("res=" + res)
  }

  def sum(n1: Int, n2: Int): Int = {
    println("sum被执行。。。")
    return n1 + n2
  }

  @tailrec
  def myWhile(condition: => Boolean)(op: => Unit): Unit = {

    if (condition) {
      op
      myWhile(condition)(op)
    }
  }

  //def foo(a: Int):Unit = {
  def fooo(a: => Int): Unit = { //注意这里变量a没有小括号了
    println(a)
    println(a)

  }

  def foo(a: Int): Unit = {
    println(a)
    println(a)
  }

  def test(i: Int): Int = {
    if (i == 1) {
      1
    } else {
      i * test(i - 1)
    }
  }
}
